package com.yyfax.common.toast;

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import com.yyfax.common.tools.DensityUtil;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * http://caizhitao.com/2016/02/09/android-toast-compat/
 * Created by ying_he on 2017/5/2.<br>
 * Copyright  2017 www.yylending.com. All Rights Reserved.<br><br>
 */
class CustomToast {
    private static final long SHORT_DURATION_MILLIS = 2000;
    private static final long LONG_DURATION_MILLIS = 3500;
    private static final int TRANSLATION_Y = 64;
    private static final int TRANSLATION_X = 0;

    // 原子操作：判断当前是否在读取{@linkplain #sToastsQueue 队列}来显示toast
    private static AtomicInteger sAtomicInteger = new AtomicInteger(0);
    private static Handler sHandler = new Handler();
    // 维护toast的队列
    private static BlockingQueue<CustomToast> sToastsQueue = new LinkedBlockingQueue<>();
    private static WindowManager sWManager;
    private static final Runnable sHide = new Runnable() {
        @Override
        public void run() {
            handleHide();
        }
    };
    private static final Runnable sActive = new Runnable() {
        @Override
        public void run() {
            activeQueue();
        }
    };
    
    private Context mContext;
    private long mDurationMillis;
    private View mView;
    private WindowManager.LayoutParams mLParams;
    private final Runnable mShow = new Runnable() {
        @Override
        public void run() {
            handleShow();
        }
    };

    private CustomToast(Context context) {
        mContext = context;
    }

    static CustomToast makeText(Context context, String text, long duration) {
        CustomToast toast = new CustomToast(context);

        sWManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        toast.mLParams = new WindowManager.LayoutParams();
        toast.mLParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        toast.mLParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        toast.mLParams.format = PixelFormat.TRANSLUCENT;
        toast.mLParams.setTitle("CustomToast");
        toast.mLParams.windowAnimations = android.R.style.Animation_Toast;
        toast.mLParams.type = WindowManager.LayoutParams.TYPE_TOAST;
        toast.mLParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        toast.mLParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        toast.mLParams.y = DensityUtil.dip2px(context, TRANSLATION_Y);
        toast.mLParams.x = TRANSLATION_X;

        toast.setText(text);
        toast.setDuration(duration);

        return toast;
    }

    static CustomToast makeText(Context context, int textId, long durationMillis) {
        return makeText(context, context.getResources().getText(textId).toString(), durationMillis);
    }

    /**
     * 轮询查找队列需要展示的toast.
     */
    private static void activeQueue() {
        CustomToast customToast = sToastsQueue.peek();
        if (customToast == null) {
             /*如果不能从队列中获取到toast的话，那么就表示已经展示完所有的toast了
             这个时候需要标记队列状态为：非激活读取中*/
            sAtomicInteger.decrementAndGet();
        } else {
            /*如果还能从队列中获取到toast的话，那么就表示还有toast没有展示
            1. 展示队首的toast
            2. 设置一定时间后主动采取toast消失措施
            3. 设置展示完毕之后再次执行本逻辑，以展示下一个toast*/
            sHandler.post(customToast.mShow);
            sHandler.postDelayed(sHide, customToast.mDurationMillis);
            sHandler.postDelayed(sActive, customToast.mDurationMillis);
        }
    }

    /**
     * 隐藏并清除已展示的toast.
     */
    private static void handleHide() {
        CustomToast customToast = sToastsQueue.peek();
        if (customToast != null) {
            if (customToast.mView != null) {
            /*note: checking parent() just to make sure the view has
            been added...  i have seen cases where we get here when
            the view isn't yet added, so let's try not to crash.*/
                if (customToast.mView.getParent() != null) {
                    sWManager.removeView(customToast.mView);
                }
                customToast.mView = null;
            }
            // 同时从队列中移除这个toast
            sToastsQueue.poll();
        }
    }

    private CustomToast setDuration(long durationMillis) {
        if (durationMillis < 0) {
            mDurationMillis = SHORT_DURATION_MILLIS;
        }
        if (durationMillis == CompatToast.LENGTH_SHORT) {
            mDurationMillis = SHORT_DURATION_MILLIS;
        } else if (durationMillis == CompatToast.LENGTH_LONG) {
            mDurationMillis = LONG_DURATION_MILLIS;
        } else {
            mDurationMillis = durationMillis;
        }
        return this;
    }

    private CustomToast setView(View view) {
        mView = view;
        return this;
    }

    private CustomToast setMargin(float horizontalMargin, float verticalMargin) {
        mLParams.horizontalMargin = horizontalMargin;
        mLParams.verticalMargin = verticalMargin;
        return this;
    }

    private CustomToast setText(String text) {
        /*模拟Toast的布局文件 com.android.internal.R.layout.transient_notification
        虽然可以手动用java写，但是不同厂商系统，这个布局的设置好像是不同的，因此我们自己获取原生Toast的view进行配置*/
        View view = android.widget.Toast.makeText(mContext, text,
                android.widget.Toast.LENGTH_SHORT).getView();
        if (view != null) {
            TextView tv = (TextView) view.findViewById(android.R.id.message);
            tv.setText(text);
            setView(view);
        }

        return this;
    }

    private CustomToast setText(int resId) {
        setText(mContext.getText(resId).toString());
        return this;
    }

    public void show() {
        // 1. 将本次需要显示的toast加入到队列中
        sToastsQueue.offer(this);
        // 2. 如果队列还没有激活，就激活队列，依次展示队列中的toast
        if (0 == sAtomicInteger.get()) {
            sAtomicInteger.incrementAndGet();
            sHandler.post(sActive);
        }
    }

    private void handleShow() {
        if (mView != null) {
            if (mView.getParent() != null) {
                sWManager.removeView(mView);
            }
            sWManager.addView(mView, mLParams);
        }
    }
}
